/*
 * logic is same as FilePrinterScala.scala, but with pure scala coding style
 * which try all the best to avoid generating&handling "null"
 */

package helloscala.practise.chapter13

import java.io.File
import java.io.FileReader
import java.io.IOException
import java.io.LineNumberReader
import java.io.Reader

class ScalaIOException(cause: Throwable) extends RuntimeException(cause)

class ScalaLineNumberReader(in: Reader) extends LineNumberReader(in) {
  def inputLine = readLine() match {
    case null => None
    case line => Some(line) //any type which is not null
  }
}
object ScalaLineNumberReader {
  def apply(in: Reader) = try {
    new ScalaLineNumberReader(in)
  } catch {
    case ex: IOException => throw new ScalaIOException(ex)
  }
}

class FilePrinterScalaOptimized(val file: File) {
  @throws(classOf[IOException])
  def printFile = {
    var reader = ScalaLineNumberReader(new FileReader(file))
    try {
      loop(reader)
    } finally {
      if (reader != null)
        reader.close
    }
  }

  def loop(reader: ScalaLineNumberReader): Unit = {
    reader.inputLine match {
      case None => //do nothing and no more recursion
      case Some(line) => {
        print(format("%3d: %s\n", reader.getLineNumber, line))
        loop(reader) //tailed recursion
      }
    }
  }
}
